1. Field of the Invention
The present invention relates to a profiling technology for software, and in particular, relates to a method and apparatus for profiling native method calls.
2. Description of Relevant Art
By tracing executive processes of an application program, various performance parameters in the execution process can be obtained, so as to locate program performance bottlenecks and then optimize the application program accordingly. The technology on which such techniques are based is referred to as profiling technology.
Native method is one directly running on a local hardware platform without interpretation by a Virtual Machine (VM). Typically, the native method can be used to directly manipulate computer hardware, improve program execution performance, reuse legacy code, etc. In an application such as Java application, native method calls are quite popular, mainly because many functions have to be implemented by native methods. For example, I/O implementation of object serialization for distributed computing, communication on high speed networks (critical links in multi-tiered applications), Java Machine (JVM) framework, mathematical calculation and etc, their implementations all rely on use of native methods.
It has been practically proved that in the case of using native methods, it is highly likely that application bottlenecks reside either in native codes or at native layer. Thus, profiling native method calls are indispensable in profiling application programs.
In the prior art, there have already been several technologies for profiling native functions, one being bytecode-level instrumentation based technology, and the other being JVM Tool Interface (JVMTI) method level event tracing technology.
The bytecode-level instrumentation based technology can be further divided into a static instrumentation and a dynamic instrumentation. In the static instrumentation, all JDK classes and application classes are bytecode instrumented before the application is executed. Since the static bytecode instrumentation requires performing a class search, the instrumentation process takes a rather long time, especially for a large application program, which takes a much longer time. For the static instrumentation, the bytecode is instrumented before the application program is executed, and is unable to profile dynamically loaded libraries during the process of executing the application program. Further, there is another drawback, namely, when using the static instrumentation, it requires maintaining two collections of classes, one being an instrumented collection of classes, and the other being an original collection of classes.
Different from the static instrumentation, in the dynamic instrumentation, the class is bytecode instrumented when being loaded. However, there are still some technology constraints to the dynamic instrumentation approach. For example, some caller codes are not allowed to be changed, and some calling method codes are already loaded before the bytecode gets instrumented, which will cause it to be unable to profile these calling method codes. Further, modifying these classes dynamically will have great impact on the behavior and performance of class loaders and Just-In-Time (JIT) compilers, such as notably increasing system overhead, which is not desired.
On the other hand, the JVMTI method level event tracing technology provides callbacks to methodEntry and methodExit events, thus the function “IsMethodNative( )” defined in the JVMTI specification can be used to check whether a method is a native one. Compared with the bytecode instrumentation, this approach is simple and easy to implement. However, since the JVMTI method level event tracing technology needs capturing all methods during the running process of an application program and needs performing determination on the methods, the system overhead becomes significant and the system may even slow down 100-1000 times, thereby notably affecting the system performance.
Besides the above-mentioned technologies, there is another known technology to profile the native method calls. For example, the current JVMTI provides a native method call-associated event, namely a NativeMethodBind event as shown below:
The NativeMethodBind event is an event where the definition of native method in the Java program is bound together with the address of a specific native method code, which is typically fired when the native method is called at the first time. Each time the NativeMethodBind event is started, some important information can be returned through parameters defined in the event. For example, “thread” can return the thread requesting for binding, “method” can return the bound method, and “address” can return the address of the bound native method. Besides, if “new_adress_ptr” is set, the VM will bind the native method call to the code address assigned by the new_address_ptr.
In this way, the address “address” of the bound native method can be obtained from this event. Further, as shown in FIG. 1, by setting the new address parameter new_address_ptr as the address of for example the profiling code, the address of the native method in the Java input/output file stream is replaced with the address of the profiling code, thereby executing the profiling code and profiling the native method call.
If this mechanism is used, it is necessary to provide an associated proxy or a wrapper to each native method, so as to perform profiling task and call the native method. If the associated proxy is executable in a proper way, a better result can be achieved, with trivial influence on the performance of the system when the application is running. However, in practice, parameter type and return type of each native method are different, thus it is necessary to implement the above replacement, and each associated proxy should have the exactly same signature as the method to be profiled. But based on the current technology, it is unable to predict the signature of a dynamically loaded method, thus it is impractical in real-life applications.